package cn.edu.scau.cmi.ema.service;

import cn.edu.scau.cmi.ema.base.CmiPagination;
import cn.edu.scau.cmi.ema.domain.*;
import cn.edu.scau.cmi.ema.service.base.CmiEmaService;
import cn.edu.scau.cmi.ema.util.CmiSqlUtil;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Query;
import java.util.*;
@Service("EventService")
@Transactional

public class EventServiceImpl extends CmiEmaService implements EventService {
	public EventServiceImpl() {
	}

	@Transactional
	public Event saveEvent(Event event) {
		Set<Event> existingEventsForParent = new HashSet<Event>();
		Set<Adultertype> existingAdultertypesForAdultertype = new HashSet<Adultertype>();
		Set<Discoverylink> existingDiscoverylinksForDiscoverylink = new HashSet<Discoverylink>();
		Set<Law> existingLawsForLaw = new HashSet<Law>();
		Set<Motive> existingMotivesForMotive = new HashSet<Motive>();
		Set<Eventadulterlink> existingEventadulterlinksForEvent = new HashSet<Eventadulterlink>();
		Set<Eventhazard> existingEventhazardsForEvent = new HashSet<Eventhazard>();
		Set<Eventpunish> existingEventpunishsForEvent = new HashSet<Eventpunish>();
		Set<Eventqualitytype> existingEventqualitytypesForEvent = new HashSet<Eventqualitytype>();
		Set<Eventquantitytype> existingEventquantitytypesForEvent = new HashSet<Eventquantitytype>();
		Set<Picture> existingPicturesForEvent = new HashSet<Picture>();
		Set<Video> existingVideosForEvent = new HashSet<Video>();

		Set<Event> selectedEventsForParent = event.getEventsForParent();
		Set<Adultertype> selectedAdultertypesForAdultertype = event.getAdultertypesForEvent();
		Set<Discoverylink> selectedDiscoverylinksForDiscoverylink = event.getDiscoverylinksForEvent();
		Set<Law> selectedLawsForLaw = event.getLawsForEvent();
		Set<Motive> selectedMotivesForMotive = event.getMotivesForEvent();
		Set<Eventadulterlink> selectedEventadulterlinksForEvent = event.getEventadulterlinksForEvent();
		Set<Eventhazard> selectedEventhazardsForEvent = event.getEventhazardsForEvent();
		Set<Eventpunish> selectedEventpunishsForEvent = event.getEventpunishsForEvent();
		Set<Eventqualitytype> selectedEventqualitytypesForEvent = event.getEventqualitytypesForEvent();
		Set<Eventquantitytype> selectedEventquantitytypesForEvent = event.getEventquantitytypesForEvent();
		Set<Picture> selectedPicturesForEvent = event.getPicturesForEvent();
		Set<Video> selectedVideosForEvent = event.getVideosForEvent();

		if (event.getId() == null) {
			Address sourceAddress = addressDAO.findAddressById(event.getSourceAddress().getId());
			Address discoveryAddress = addressDAO.findAddressById(event.getDiscoveryAddress().getId());
			Subject subject = subjectDAO.findSubjectById(event.getSubject().getId());
			User auditor = userDAO.findUserById(event.getAuditor().getId());
			Url url = urlDAO.findUrlById(event.getUrl().getId());
			User reportor = userDAO.findUserById(event.getReportor().getId());
			Event parent = eventDAO.findEventById(event.getParent().getId());
			Foodbatch foodbatch = foodbatchDAO.findFoodbatchById(event.getFoodbatch().getId());

			Event existingEvent = eventDAO.findEventByPhysicalPrimaryKey(subject.getId(), foodbatch.getId());

			event.setSourceAddress(sourceAddress);
			event.setDiscoveryAddress(discoveryAddress);
			event.setSubject(subject);
			event.setAuditor(auditor);
			event.setUrl(url);
			event.setReportor(reportor);
			event.setParent(parent);
			event.setFoodbatch(foodbatch);

			if (isEquals(event, existingEvent)) {
				return existingEvent;
			}

			event = eventDAO.store(event);
			eventDAO.flush();

			for (Event relatedEvent : selectedEventsForParent) {
				relatedEvent.setParent(event);
				eventDAO.store(relatedEvent);
			}

			for (Adultertype relatedAdultertype : selectedAdultertypesForAdultertype) {
				relatedAdultertype.getEventsForAdultertype().add(event);
				adultertypeDAO.store(relatedAdultertype);
			}

			for (Discoverylink relatedDiscoverylink : selectedDiscoverylinksForDiscoverylink) {
				relatedDiscoverylink.getEventsForDiscoverylink().add(event);
				discoverylinkDAO.store(relatedDiscoverylink);
			}

			for (Law relatedLaw : selectedLawsForLaw) {
				relatedLaw.getEventsForLaw().add(event);
				lawDAO.store(relatedLaw);
			}

			for (Motive relatedMotive : selectedMotivesForMotive) {
				relatedMotive.getEventsForMotive().add(event);
				motiveDAO.store(relatedMotive);
			}
			for (Eventadulterlink relatedEventadulterlink : selectedEventadulterlinksForEvent) {
				relatedEventadulterlink.setEvent(event);
				eventadulterlinkDAO.store(relatedEventadulterlink);
			}
			for (Eventhazard relatedEventhazard : selectedEventhazardsForEvent) {
				relatedEventhazard.setEvent(event);
				eventhazardDAO.store(relatedEventhazard);
			}
			for (Eventpunish relatedEventpunish : selectedEventpunishsForEvent) {
				relatedEventpunish.setEvent(event);
				eventpunishDAO.store(relatedEventpunish);
			}
			for (Eventqualitytype relatedEventqualitytype : selectedEventqualitytypesForEvent) {
				relatedEventqualitytype.setEvent(event);
				eventqualitytypeDAO.store(relatedEventqualitytype);
			}
			for (Eventquantitytype relatedEventquantitytype : selectedEventquantitytypesForEvent) {
				relatedEventquantitytype.setEvent(event);
				eventquantitytypeDAO.store(relatedEventquantitytype);
			}
			for (Picture relatedPicture : selectedPicturesForEvent) {
				relatedPicture.setEvent(event);
				pictureDAO.store(relatedPicture);
			}
			for (Video relatedVideo : selectedVideosForEvent) {
				relatedVideo.setEvent(event);
				videoDAO.store(relatedVideo);
			}
		} else {
			Event existingEvent = eventDAO.findEventByPrimaryKey(event.getId());

			existingEventsForParent = existingEvent.getEventsForParent();
			existingAdultertypesForAdultertype = existingEvent.getAdultertypesForEvent();
			existingDiscoverylinksForDiscoverylink = existingEvent.getDiscoverylinksForEvent();
			existingLawsForLaw = existingEvent.getLawsForEvent();
			existingMotivesForMotive = existingEvent.getMotivesForEvent();
			existingEventadulterlinksForEvent = existingEvent.getEventadulterlinksForEvent();
			existingEventhazardsForEvent = existingEvent.getEventhazardsForEvent();
			existingEventpunishsForEvent = existingEvent.getEventpunishsForEvent();
			existingEventqualitytypesForEvent = existingEvent.getEventqualitytypesForEvent();
			existingEventquantitytypesForEvent = existingEvent.getEventquantitytypesForEvent();
			existingPicturesForEvent = existingEvent.getPicturesForEvent();
			existingVideosForEvent = existingEvent.getVideosForEvent();

			Set<Event> prepareDeleteEventsForParent = new HashSet<Event>();
			Set<Event> prepareAddEventsForParent = new HashSet<Event>();

			prepareDeleteEventsForParent.addAll(selectedEventsForParent);
			prepareDeleteEventsForParent.addAll(existingEventsForParent);

			prepareAddEventsForParent.addAll(selectedEventsForParent);
			prepareAddEventsForParent.addAll(existingEventsForParent);

			prepareDeleteEventsForParent.removeAll(selectedEventsForParent);
			prepareAddEventsForParent.removeAll(existingEventsForParent);

			for (Event relatedEvent : prepareAddEventsForParent) {
				relatedEvent.setParent(event);
				eventDAO.store(relatedEvent);
			}

			for (Event relatedEvent : prepareDeleteEventsForParent) {
				relatedEvent.setParent(null);
				eventDAO.store(relatedEvent);
			}
			Set<Adultertype> prepareDeleteAdultertypesForAdultertype = new HashSet<Adultertype>();
			Set<Adultertype> prepareAddAdultertypesForAdultertype = new HashSet<Adultertype>();

			prepareDeleteAdultertypesForAdultertype.addAll(selectedAdultertypesForAdultertype);
			prepareDeleteAdultertypesForAdultertype.addAll(existingAdultertypesForAdultertype);

			prepareAddAdultertypesForAdultertype.addAll(selectedAdultertypesForAdultertype);
			prepareAddAdultertypesForAdultertype.addAll(existingAdultertypesForAdultertype);

			prepareDeleteAdultertypesForAdultertype.removeAll(selectedAdultertypesForAdultertype);
			prepareAddAdultertypesForAdultertype.removeAll(existingAdultertypesForAdultertype);

			for (Adultertype relatedAdultertype : prepareAddAdultertypesForAdultertype) {

				relatedAdultertype.getEventsForAdultertype().add(existingEvent);
				adultertypeDAO.store(relatedAdultertype);
			}

			for (Adultertype relatedAdultertype : prepareDeleteAdultertypesForAdultertype) {

				relatedAdultertype.getEventsForAdultertype().remove(existingEvent);
				adultertypeDAO.store(relatedAdultertype);
			}
			Set<Discoverylink> prepareDeleteDiscoverylinksForDiscoverylink = new HashSet<Discoverylink>();
			Set<Discoverylink> prepareAddDiscoverylinksForDiscoverylink = new HashSet<Discoverylink>();

			prepareDeleteDiscoverylinksForDiscoverylink.addAll(selectedDiscoverylinksForDiscoverylink);
			prepareDeleteDiscoverylinksForDiscoverylink.addAll(existingDiscoverylinksForDiscoverylink);

			prepareAddDiscoverylinksForDiscoverylink.addAll(selectedDiscoverylinksForDiscoverylink);
			prepareAddDiscoverylinksForDiscoverylink.addAll(existingDiscoverylinksForDiscoverylink);

			prepareDeleteDiscoverylinksForDiscoverylink.removeAll(selectedDiscoverylinksForDiscoverylink);
			prepareAddDiscoverylinksForDiscoverylink.removeAll(existingDiscoverylinksForDiscoverylink);

			for (Discoverylink relatedDiscoverylink : prepareAddDiscoverylinksForDiscoverylink) {

				relatedDiscoverylink.getEventsForDiscoverylink().add(existingEvent);
				discoverylinkDAO.store(relatedDiscoverylink);
			}

			for (Discoverylink relatedDiscoverylink : prepareDeleteDiscoverylinksForDiscoverylink) {

				relatedDiscoverylink.getEventsForDiscoverylink().remove(existingEvent);
				discoverylinkDAO.store(relatedDiscoverylink);
			}
			Set<Law> prepareDeleteLawsForLaw = new HashSet<Law>();
			Set<Law> prepareAddLawsForLaw = new HashSet<Law>();

			prepareDeleteLawsForLaw.addAll(selectedLawsForLaw);
			prepareDeleteLawsForLaw.addAll(existingLawsForLaw);

			prepareAddLawsForLaw.addAll(selectedLawsForLaw);
			prepareAddLawsForLaw.addAll(existingLawsForLaw);

			prepareDeleteLawsForLaw.removeAll(selectedLawsForLaw);
			prepareAddLawsForLaw.removeAll(existingLawsForLaw);

			for (Law relatedLaw : prepareAddLawsForLaw) {

				relatedLaw.getEventsForLaw().add(existingEvent);
				lawDAO.store(relatedLaw);
			}

			for (Law relatedLaw : prepareDeleteLawsForLaw) {

				relatedLaw.getEventsForLaw().remove(existingEvent);
				lawDAO.store(relatedLaw);
			}
			Set<Motive> prepareDeleteMotivesForMotive = new HashSet<Motive>();
			Set<Motive> prepareAddMotivesForMotive = new HashSet<Motive>();

			prepareDeleteMotivesForMotive.addAll(selectedMotivesForMotive);
			prepareDeleteMotivesForMotive.addAll(existingMotivesForMotive);

			prepareAddMotivesForMotive.addAll(selectedMotivesForMotive);
			prepareAddMotivesForMotive.addAll(existingMotivesForMotive);

			prepareDeleteMotivesForMotive.removeAll(selectedMotivesForMotive);
			prepareAddMotivesForMotive.removeAll(existingMotivesForMotive);

			for (Motive relatedMotive : prepareAddMotivesForMotive) {

				relatedMotive.getEventsForMotive().add(existingEvent);
				motiveDAO.store(relatedMotive);
			}

			for (Motive relatedMotive : prepareDeleteMotivesForMotive) {

				relatedMotive.getEventsForMotive().remove(existingEvent);
				motiveDAO.store(relatedMotive);
			}
			Set<Eventadulterlink> prepareDeleteEventadulterlinksForEvent = new HashSet<Eventadulterlink>();
			Set<Eventadulterlink> prepareAddEventadulterlinksForEvent = new HashSet<Eventadulterlink>();

			prepareDeleteEventadulterlinksForEvent.addAll(selectedEventadulterlinksForEvent);
			prepareDeleteEventadulterlinksForEvent.addAll(existingEventadulterlinksForEvent);

			prepareAddEventadulterlinksForEvent.addAll(selectedEventadulterlinksForEvent);
			prepareAddEventadulterlinksForEvent.addAll(existingEventadulterlinksForEvent);

			prepareDeleteEventadulterlinksForEvent.removeAll(selectedEventadulterlinksForEvent);
			prepareAddEventadulterlinksForEvent.removeAll(existingEventadulterlinksForEvent);

			for (Eventadulterlink relatedEventadulterlink : prepareAddEventadulterlinksForEvent) {
				relatedEventadulterlink.setEvent(event);
				eventadulterlinkDAO.store(relatedEventadulterlink);
			}

			for (Eventadulterlink relatedEventadulterlink : prepareDeleteEventadulterlinksForEvent) {
				relatedEventadulterlink.setEvent(null);
				eventadulterlinkDAO.store(relatedEventadulterlink);
			}
			Set<Eventhazard> prepareDeleteEventhazardsForEvent = new HashSet<Eventhazard>();
			Set<Eventhazard> prepareAddEventhazardsForEvent = new HashSet<Eventhazard>();

			prepareDeleteEventhazardsForEvent.addAll(selectedEventhazardsForEvent);
			prepareDeleteEventhazardsForEvent.addAll(existingEventhazardsForEvent);

			prepareAddEventhazardsForEvent.addAll(selectedEventhazardsForEvent);
			prepareAddEventhazardsForEvent.addAll(existingEventhazardsForEvent);

			prepareDeleteEventhazardsForEvent.removeAll(selectedEventhazardsForEvent);
			prepareAddEventhazardsForEvent.removeAll(existingEventhazardsForEvent);

			for (Eventhazard relatedEventhazard : prepareAddEventhazardsForEvent) {
				relatedEventhazard.setEvent(event);
				eventhazardDAO.store(relatedEventhazard);
			}

			for (Eventhazard relatedEventhazard : prepareDeleteEventhazardsForEvent) {
				relatedEventhazard.setEvent(null);
				eventhazardDAO.store(relatedEventhazard);
			}
			Set<Eventpunish> prepareDeleteEventpunishsForEvent = new HashSet<Eventpunish>();
			Set<Eventpunish> prepareAddEventpunishsForEvent = new HashSet<Eventpunish>();

			prepareDeleteEventpunishsForEvent.addAll(selectedEventpunishsForEvent);
			prepareDeleteEventpunishsForEvent.addAll(existingEventpunishsForEvent);

			prepareAddEventpunishsForEvent.addAll(selectedEventpunishsForEvent);
			prepareAddEventpunishsForEvent.addAll(existingEventpunishsForEvent);

			prepareDeleteEventpunishsForEvent.removeAll(selectedEventpunishsForEvent);
			prepareAddEventpunishsForEvent.removeAll(existingEventpunishsForEvent);

			for (Eventpunish relatedEventpunish : prepareAddEventpunishsForEvent) {
				relatedEventpunish.setEvent(event);
				eventpunishDAO.store(relatedEventpunish);
			}

			for (Eventpunish relatedEventpunish : prepareDeleteEventpunishsForEvent) {
				relatedEventpunish.setEvent(null);
				eventpunishDAO.store(relatedEventpunish);
			}
			Set<Eventqualitytype> prepareDeleteEventqualitytypesForEvent = new HashSet<Eventqualitytype>();
			Set<Eventqualitytype> prepareAddEventqualitytypesForEvent = new HashSet<Eventqualitytype>();

			prepareDeleteEventqualitytypesForEvent.addAll(selectedEventqualitytypesForEvent);
			prepareDeleteEventqualitytypesForEvent.addAll(existingEventqualitytypesForEvent);

			prepareAddEventqualitytypesForEvent.addAll(selectedEventqualitytypesForEvent);
			prepareAddEventqualitytypesForEvent.addAll(existingEventqualitytypesForEvent);

			prepareDeleteEventqualitytypesForEvent.removeAll(selectedEventqualitytypesForEvent);
			prepareAddEventqualitytypesForEvent.removeAll(existingEventqualitytypesForEvent);

			for (Eventqualitytype relatedEventqualitytype : prepareAddEventqualitytypesForEvent) {
				relatedEventqualitytype.setEvent(event);
				eventqualitytypeDAO.store(relatedEventqualitytype);
			}

			for (Eventqualitytype relatedEventqualitytype : prepareDeleteEventqualitytypesForEvent) {
				relatedEventqualitytype.setEvent(null);
				eventqualitytypeDAO.store(relatedEventqualitytype);
			}
			Set<Eventquantitytype> prepareDeleteEventquantitytypesForEvent = new HashSet<Eventquantitytype>();
			Set<Eventquantitytype> prepareAddEventquantitytypesForEvent = new HashSet<Eventquantitytype>();

			prepareDeleteEventquantitytypesForEvent.addAll(selectedEventquantitytypesForEvent);
			prepareDeleteEventquantitytypesForEvent.addAll(existingEventquantitytypesForEvent);

			prepareAddEventquantitytypesForEvent.addAll(selectedEventquantitytypesForEvent);
			prepareAddEventquantitytypesForEvent.addAll(existingEventquantitytypesForEvent);

			prepareDeleteEventquantitytypesForEvent.removeAll(selectedEventquantitytypesForEvent);
			prepareAddEventquantitytypesForEvent.removeAll(existingEventquantitytypesForEvent);

			for (Eventquantitytype relatedEventquantitytype : prepareAddEventquantitytypesForEvent) {
				relatedEventquantitytype.setEvent(event);
				eventquantitytypeDAO.store(relatedEventquantitytype);
			}

			for (Eventquantitytype relatedEventquantitytype : prepareDeleteEventquantitytypesForEvent) {
				relatedEventquantitytype.setEvent(null);
				eventquantitytypeDAO.store(relatedEventquantitytype);
			}
			Set<Picture> prepareDeletePicturesForEvent = new HashSet<Picture>();
			Set<Picture> prepareAddPicturesForEvent = new HashSet<Picture>();

			prepareDeletePicturesForEvent.addAll(selectedPicturesForEvent);
			prepareDeletePicturesForEvent.addAll(existingPicturesForEvent);

			prepareAddPicturesForEvent.addAll(selectedPicturesForEvent);
			prepareAddPicturesForEvent.addAll(existingPicturesForEvent);

			prepareDeletePicturesForEvent.removeAll(selectedPicturesForEvent);
			prepareAddPicturesForEvent.removeAll(existingPicturesForEvent);

			for (Picture relatedPicture : prepareAddPicturesForEvent) {
				relatedPicture.setEvent(event);
				pictureDAO.store(relatedPicture);
			}

			for (Picture relatedPicture : prepareDeletePicturesForEvent) {
				relatedPicture.setEvent(null);
				pictureDAO.store(relatedPicture);
			}
			Set<Video> prepareDeleteVideosForEvent = new HashSet<Video>();
			Set<Video> prepareAddVideosForEvent = new HashSet<Video>();

			prepareDeleteVideosForEvent.addAll(selectedVideosForEvent);
			prepareDeleteVideosForEvent.addAll(existingVideosForEvent);

			prepareAddVideosForEvent.addAll(selectedVideosForEvent);
			prepareAddVideosForEvent.addAll(existingVideosForEvent);

			prepareDeleteVideosForEvent.removeAll(selectedVideosForEvent);
			prepareAddVideosForEvent.removeAll(existingVideosForEvent);

			for (Video relatedVideo : prepareAddVideosForEvent) {
				relatedVideo.setEvent(event);
				videoDAO.store(relatedVideo);
			}

			for (Video relatedVideo : prepareDeleteVideosForEvent) {
				relatedVideo.setEvent(null);
				videoDAO.store(relatedVideo);
			}
			event = eventDAO.store(event);
			eventDAO.flush();
		}

		eventDAO.flush();
		adultertypeDAO.flush();
		discoverylinkDAO.flush();
		lawDAO.flush();
		motiveDAO.flush();
		eventadulterlinkDAO.flush();
		eventhazardDAO.flush();
		eventpunishDAO.flush();
		eventqualitytypeDAO.flush();
		eventquantitytypeDAO.flush();
		pictureDAO.flush();
		videoDAO.flush();
		return event;
	}

	public void deleteEvent(Event event) {
		eventDAO.remove(event);
		eventDAO.flush();
	}

	@Transactional
	public void deleteEvents(Set<Integer> deleteEventsId) {
		Query query = eventDAO.createNamedQuery("deleteEventsById", -1, -1);
		query.setParameter(1, deleteEventsId);
		query.executeUpdate();
	}

	@Transactional
	public Set<Event> loadEvents() {
		return eventDAO.findAllEvents();

	}

	@Transactional
	public Set<Event> loadReferenceEvents(Set<Event> events) {
		Iterator<Event> eventsIterator = events.iterator();
		Set<Event> referencedEvents = new HashSet<>();
		while (eventsIterator.hasNext()) {
			Event currentEvent = eventsIterator.next();

			if (!currentEvent.getEventsForParent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getAdultertypesForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getDiscoverylinksForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getLawsForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getMotivesForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getEventadulterlinksForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getEventhazardsForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getEventpunishsForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getEventqualitytypesForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getEventquantitytypesForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getPicturesForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}

			if (!currentEvent.getVideosForEvent().isEmpty()) {
				referencedEvents.add(currentEvent);
				continue;
			}
		}
		return referencedEvents;
	}

	public Set<Event> loadEventsByIdSet(Set<Integer> eventIdSet) {

		Iterator<Integer> eventIdIterator = eventIdSet.iterator();
		Set<Event> eventSet = new HashSet<>();
		while (eventIdIterator.hasNext()) {
			Integer id = eventIdIterator.next();
			Event currentEvent = eventDAO.findEventById(id);
			eventSet.add(currentEvent);
		}
		return eventSet;
	}

	@Transactional
	public List<Event> findAllEvents(Integer startResult, Integer maxRows) {
		return new java.util.ArrayList<Event>(eventDAO.findAllEvents(startResult, maxRows));
	}

	@Transactional
	public Event findEventByPrimaryKey(Integer id) {
		return eventDAO.findEventByPrimaryKey(id);
	}

	@Transactional
	public Integer countEvents() {
		return ((Long) eventDAO.createQuerySingleResult("select count(o) from Event o").getSingleResult()).intValue();
	}

	@Transactional
	public Integer countEvents(CmiPagination page) {
		String sql = CmiSqlUtil.createCountHql(page, Event.class);
		return ((Long) eventDAO.createQuerySingleResult(sql).getSingleResult()).intValue();
	}

	/**
	 * search for name with ajax
	 *
	 */
	@Transactional
	public Integer countEventsByName(String queryName) {
		Query query = eventDAO.createNamedQuery("countEventsByName", -1, -1);
		query.setParameter(1, queryName);
		return new Long((long) query.getSingleResult()).intValue();
	}

	@Transactional
	public Integer countEventsByDetachedCriteria(CmiPagination page) {
		DetachedCriteria detachedCriteria = CmiSqlUtil.createDetachedCriteria(page, Event.class);
		Session session = (Session) entityManager.getDelegate();
		detachedCriteria.setProjection(Projections.rowCount());
		return new Long((long) detachedCriteria.getExecutableCriteria(session).uniqueResult()).intValue();
	}

	public Map<String, ?> loadEventObjectReferencedSet(Event event) {
		HashMap<String, Object> objectReferencedSetMap = new HashMap<>();
		if (event.getSourceAddress() != null) {

			Set<Integer> sourceAddressIds = new HashSet<Integer>();
			sourceAddressIds.add(event.getSourceAddress().getId());
			objectReferencedSetMap.put("sourceAddressIds", sourceAddressIds);
		}
		if (event.getDiscoveryAddress() != null) {

			Set<Integer> discoveryAddressIds = new HashSet<Integer>();
			discoveryAddressIds.add(event.getDiscoveryAddress().getId());
			objectReferencedSetMap.put("discoveryAddressIds", discoveryAddressIds);
		}
		if (event.getSubject() != null) {

			Set<Integer> subjectIds = new HashSet<Integer>();
			subjectIds.add(event.getSubject().getId());
			objectReferencedSetMap.put("subjectIds", subjectIds);
		}
		if (event.getAuditor() != null) {

			Set<Integer> auditorIds = new HashSet<Integer>();
			auditorIds.add(event.getAuditor().getId());
			objectReferencedSetMap.put("auditorIds", auditorIds);
		}
		if (event.getUrl() != null) {

			Set<Integer> urlIds = new HashSet<Integer>();
			urlIds.add(event.getUrl().getId());
			objectReferencedSetMap.put("urlIds", urlIds);
		}
		if (event.getReportor() != null) {

			Set<Integer> reportorIds = new HashSet<Integer>();
			reportorIds.add(event.getReportor().getId());
			objectReferencedSetMap.put("reportorIds", reportorIds);
		}
		if (event.getParent() != null) {

			Set<Integer> parentIds = new HashSet<Integer>();
			parentIds.add(event.getParent().getId());
			objectReferencedSetMap.put("parentIds", parentIds);
		}
		if (event.getFoodbatch() != null) {

			Set<Integer> foodbatchIds = new HashSet<Integer>();
			foodbatchIds.add(event.getFoodbatch().getId());
			objectReferencedSetMap.put("foodbatchIds", foodbatchIds);
		}

		Set<Integer> eventsIds = new HashSet<Integer>();
		for (Event obj : event.getEventsForParent()) {

			eventsIds.add(obj.getId());
		}
		objectReferencedSetMap.put("eventsIds", eventsIds);
		Set<Integer> adultertypesIds = new HashSet<Integer>();
		for (Adultertype adultertype : event.getAdultertypesForEvent()) {
			adultertypesIds.add(adultertype.getId());
		}
		objectReferencedSetMap.put("adultertypesIds", adultertypesIds);
		Set<Integer> discoverylinksIds = new HashSet<Integer>();
		for (Discoverylink discoverylink : event.getDiscoverylinksForEvent()) {
			discoverylinksIds.add(discoverylink.getId());
		}
		objectReferencedSetMap.put("discoverylinksIds", discoverylinksIds);
		Set<Integer> lawsIds = new HashSet<Integer>();
		for (Law law : event.getLawsForEvent()) {
			lawsIds.add(law.getId());
		}
		objectReferencedSetMap.put("lawsIds", lawsIds);
		Set<Integer> motivesIds = new HashSet<Integer>();
		for (Motive motive : event.getMotivesForEvent()) {
			motivesIds.add(motive.getId());
		}
		objectReferencedSetMap.put("motivesIds", motivesIds);
		Set<Integer> eventadulterlinksIds = new HashSet<Integer>();
		for (Eventadulterlink obj : event.getEventadulterlinksForEvent()) {

			eventadulterlinksIds.add(obj.getId());
		}
		objectReferencedSetMap.put("eventadulterlinksIds", eventadulterlinksIds);
		Set<Integer> eventhazardsIds = new HashSet<Integer>();
		for (Eventhazard obj : event.getEventhazardsForEvent()) {

			eventhazardsIds.add(obj.getId());
		}
		objectReferencedSetMap.put("eventhazardsIds", eventhazardsIds);
		Set<Integer> eventpunishsIds = new HashSet<Integer>();
		for (Eventpunish obj : event.getEventpunishsForEvent()) {

			eventpunishsIds.add(obj.getId());
		}
		objectReferencedSetMap.put("eventpunishsIds", eventpunishsIds);
		Set<Integer> eventqualitytypesIds = new HashSet<Integer>();
		for (Eventqualitytype obj : event.getEventqualitytypesForEvent()) {

			eventqualitytypesIds.add(obj.getId());
		}
		objectReferencedSetMap.put("eventqualitytypesIds", eventqualitytypesIds);
		Set<Integer> eventquantitytypesIds = new HashSet<Integer>();
		for (Eventquantitytype obj : event.getEventquantitytypesForEvent()) {

			eventquantitytypesIds.add(obj.getId());
		}
		objectReferencedSetMap.put("eventquantitytypesIds", eventquantitytypesIds);
		Set<Integer> picturesIds = new HashSet<Integer>();
		for (Picture obj : event.getPicturesForEvent()) {

			picturesIds.add(obj.getId());
		}
		objectReferencedSetMap.put("picturesIds", picturesIds);
		Set<Integer> videosIds = new HashSet<Integer>();
		for (Video obj : event.getVideosForEvent()) {

			videosIds.add(obj.getId());
		}
		objectReferencedSetMap.put("videosIds", videosIds);

		return objectReferencedSetMap;
	}

	public Map<String, ?> loadEventClassReferencedSet(Event event) {
		HashMap<String, Object> classReferencedSetMap = new HashMap<>();
		classReferencedSetMap.put("addresss", addressDAO.findAllAddresss());
		classReferencedSetMap.put("addresss", addressDAO.findAllAddresss());
		classReferencedSetMap.put("subjects", subjectDAO.findAllSubjects());
		classReferencedSetMap.put("users", userDAO.findAllUsers());
		classReferencedSetMap.put("urls", urlDAO.findAllUrls());
		classReferencedSetMap.put("users", userDAO.findAllUsers());
		classReferencedSetMap.put("foodbatchs", foodbatchDAO.findAllFoodbatchs());
		classReferencedSetMap.put("events", eventDAO.findAllEvents());
		classReferencedSetMap.put("adultertypes", adultertypeDAO.findAllAdultertypes());
		classReferencedSetMap.put("discoverylinks", discoverylinkDAO.findAllDiscoverylinks());
		classReferencedSetMap.put("laws", lawDAO.findAllLaws());
		classReferencedSetMap.put("motives", motiveDAO.findAllMotives());
		classReferencedSetMap.put("eventadulterlinks", eventadulterlinkDAO.findAllEventadulterlinks());
		classReferencedSetMap.put("eventhazards", eventhazardDAO.findAllEventhazards());
		classReferencedSetMap.put("eventpunishs", eventpunishDAO.findAllEventpunishs());
		classReferencedSetMap.put("eventqualitytypes", eventqualitytypeDAO.findAllEventqualitytypes());
		classReferencedSetMap.put("eventquantitytypes", eventquantitytypeDAO.findAllEventquantitytypes());
		classReferencedSetMap.put("pictures", pictureDAO.findAllPictures());
		classReferencedSetMap.put("videos", videoDAO.findAllVideos());

		return classReferencedSetMap;
	}

	public boolean isEquals(Event event, Object obj) {
		if (obj == event)
			return true;
		if (!(obj instanceof Event))
			return false;
		Event comparedEvent = (Event) obj;
		if (!CheckPropertyEqual(event.getSubject().getId(), comparedEvent.getSubject().getId())) {
			return false;
		}
		if (!CheckPropertyEqual(event.getFoodbatch().getId(), comparedEvent.getFoodbatch().getId())) {
			return false;
		}
		return true;
	}

	public static <T> boolean CheckPropertyEqual(T originProperty, T comparedProperty) {
		// 基本类型经过参数传递后会自动装箱
		String[] className = originProperty.getClass().getName().split("\\.");
		if (className[0].equals("java") && className[1].equals("math")) {
			return ((Comparable) originProperty).compareTo(comparedProperty) == 0 ? true : false;
		} else {
			return originProperty.equals(comparedProperty);
		}
	}
}

